package com.sanq.product.cab.tools.quartz;

import com.sanq.product.cab.tools.strings.StringUtil;
import org.quartz.*;
import org.quartz.impl.matchers.KeyMatcher;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

/**
 * com.sanq.product.cab.tools.quartz
 *
 * @author sanq.Yan
 * @date 2020/3/2
 */
public class JobManage {

    public static String getJobKey(Long id) {
        return "job:" + id;
    }

    public static String getJobGroupKey(Long id) {
        return "job:group:" + id;
    }

    public static String getTriggerKey(Long id) {
        return "trigger:" + id;
    }

    public static String getTriggerGroupKey(Long id) {
        return "trigger:group:" + id;
    }

    /**
     * 通过名称得到类名
     */
    private static Class<? extends Job> getClass(String clazz) throws ClassNotFoundException {
        return (Class<? extends Job>) Class.forName(clazz);
    }

    private static JobListener getJobListener(String clazz) throws Exception {
        return (JobListener) Class.forName(clazz).newInstance();
    }

    /**
     * 新建任务
     */
    public static void addJob(Scheduler scheduler,
                              String jobName,
                              String groupName,
                              String triggerName,
                              String triggerGroupName,
                              String cron,
                              String clazzName,
                              String extra,
                              int isCarry) throws Exception {
        addJob(scheduler, jobName, groupName, triggerName, triggerGroupName, cron, clazzName, null, extra, isCarry);
    }

    /**
     * 新建任务
     */
    public static void addJob(Scheduler scheduler,
                              String jobName,
                              String groupName,
                              String triggerName,
                              String triggerGroupName,
                              String cron,
                              String clazzName,
                              String jobListenerClazzName,
                              String extra,
                              int isCarry) throws Exception {

        Class<? extends Job> aClass = getClass(clazzName);
        JobListener jobListener = getJobListener(jobListenerClazzName);

        if (isCarry == 1) {
            JobDetail carryJob = newJob(aClass)
                    .withIdentity("carry:" + jobName, "carry:" + groupName)
                    .usingJobData("extra", extra)
                    .build();
            Trigger carryTrigger = newTrigger()
                    .withIdentity("carry:" + triggerName, "carry:" + triggerGroupName)
                    .startNow()
                    .build();

            if (!StringUtil.isEmpty(jobListenerClazzName)) {
                scheduler.getListenerManager().addJobListener(jobListener, KeyMatcher.keyEquals(JobKey.jobKey("carry:" + jobName, "carry:" + groupName)));
            }

            scheduler.scheduleJob(carryJob, carryTrigger);

        } else {
            JobDetail jobDetail = newJob(aClass)
                    .withIdentity(jobName, groupName)
                    .usingJobData("extra", extra)
                    .build();

            CronTrigger trigger = newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .withSchedule(cronSchedule(cron))
                    .build();

            if (!StringUtil.isEmpty(jobListenerClazzName)) {
                scheduler.getListenerManager().addJobListener(jobListener, KeyMatcher.keyEquals(JobKey.jobKey(jobName, groupName)));
            }

            scheduler.scheduleJob(jobDetail, trigger);
        }

        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
    }

    /**
     * 修改任务
     */
    public static void modifyJob(Scheduler scheduler,
                                 String triggerName,
                                 String triggerGroupName,
                                 String cron) throws Exception {

        TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        if (trigger == null) {
            // 新建
            trigger = newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .withSchedule(cronSchedule(cron))
                    .build();
        } else {

            String oldCron = trigger.getCronExpression();

            if (!oldCron.equals(cron)) {
                // 更新
                trigger = newTrigger()
                        .withIdentity(triggerName, triggerGroupName)
                        .withSchedule(cronSchedule(cron))
                        .build();
            }
        }

        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 移除任务
     */
    public static void removeJob(Scheduler scheduler,
                                 String jobName,
                                 String groupName,
                                 String triggerName,
                                 String triggerGroupName) throws Exception {

        JobKey jobKey = JobKey.jobKey(jobName, groupName);
        TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

        scheduler.pauseTrigger(triggerKey); // 停止触发器
        scheduler.unscheduleJob(triggerKey);    // 移除触发器
        scheduler.deleteJob(jobKey);            // 删除任务
    }

    /**
     * 暂停任务
     */
    public static void pauseJob(Scheduler scheduler, String jobName, String groupName) throws Exception {
        JobKey jobKey = JobKey.jobKey(jobName, groupName);

        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复任务
     */
    public static void restartJob(Scheduler scheduler, String jobName, String groupName) throws Exception {
        JobKey jobKey = JobKey.jobKey(jobName, groupName);
        scheduler.resumeJob(jobKey);
    }

    /**
     * 启动全部任务
     */
    public static void start(Scheduler scheduler) throws Exception {
        scheduler.start();
    }

    /**
     * 停止所有任务
     */
    public static void shutdownJob(Scheduler scheduler) throws Exception {
        if (!scheduler.isShutdown()) {
            scheduler.shutdown();
        }
    }
}
